﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using SistemaCenterQuimCentral;
using SistemaCenterQuimCentral.Reportes; //usado para imprimir el envío

using SistemaCenterQuimPost.Entidad;  //Usado para instanciar objetos de clase Producto y agilizar el filtrado de descripción.
using System.Text.RegularExpressions; //usado para expresiones regulares. Filtrar descripciones
using SistemaCenterQuimPost.Control; //usado para validar datos.
using SistemaCenterQuimPost.Plantillas; //necesario para obtener fecha, nombre usuario etc,

using System.IO;    //3 referencias que son necesarias para el proceso de archivos.
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;


namespace SistemaCenterQuimCentral.UI.CentralSupervisor
{
    public partial class frmEnviarProductosPost : SistemaCenterQuimPost.Plantillas.frmPlantillaHijo
    {
        //---------ATRIBUTOS--------------------

        //(ALE)COLOCAR BIEN ESTAS 2 INSTRUCCIONES SI ES QUE NO LO ESTÁN. 
        private DataSet3 centerQuimDs;  //Atributos usados para obtener datos de la base de datos.   

        private DataSet3TableAdapters.ProductosTableAdapter productosTa;

        private bool refrescarResgProductos; //La primera vez debe refrescar el resgProductos.

        private ArrayList resgProductos; // colección usada para guardar Codigos de productos y descripción, se tiene una pequeña base de dato para realizar las busqueda mediante filtros más rapidamente.

        private Thread oHiloActualizarResgProductos; //hilos que son ejecutados concurrentemente con la aplicación.
        private Thread oHiloFiltrarDescripcion;
        
        private string estadoDelFormulario;

        DataSet3TableAdapters.RemitosTableAdapter remitosTa;
        DataSet3TableAdapters.productoxRemitoTableAdapter productoxRemitoTa;
        DataSet3TableAdapters.MovimientosxProductosTableAdapter movimientosTa;


        //objeto para serializar los RegistroUsuario y RegistroListaPrecio en formato binario
        private BinaryFormatter aplicadorFormato = new BinaryFormatter(); //Clase que permite serializar objeto, es decir pasarlo a binario.
        private FileStream ordenCompraEntrada; //clase que maneja la información sobre el archivo y la forma de abrirlo.
        private FileStream remitoSalida; //clase que maneja la información sobre el archvi y la forma de crearlo.


        //---------CONSTRUCTORES---------------
        
        public frmEnviarProductosPost()
        {
            InitializeComponent();

            centerQuimDs = new DataSet3();

            this.productosTa = new DataSet3TableAdapters.ProductosTableAdapter();

            this.resgProductos = new ArrayList();  //se inicializa la colección ArrayList que guardará una base de datos parcial.          

            this.oHiloActualizarResgProductos = new Thread(new ThreadStart(actualizarResgProductos)); //Instancia el hilo y lo delega al metodo actualizarResgProductos. 
            this.oHiloFiltrarDescripcion = new Thread(new ThreadStart(filtrarDescripcion));
            
            estadoDelFormulario = "";

            refrescarResgProductos = true; //inicializamos a true, ya que la primera vez que trate de usar ResgProductos tendra que actualizar.
                        
            remitosTa = new DataSet3TableAdapters.RemitosTableAdapter();

            productoxRemitoTa = new DataSet3TableAdapters.productoxRemitoTableAdapter();
            movimientosTa = new DataSet3TableAdapters.MovimientosxProductosTableAdapter();

            
        }

        //---------ESTADOS---------------------

        private void frmEnviarProductosPost_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;  //necesario para trabajar con hilos.

            estEsperandoOperacion(); //estado al comenzar el formulario o al fracasar en la busqueda.

        }

        //virtual me permite redefinir, en este caso solo en las clases hijas
        protected virtual void estEsperandoOperacion() //estado luego de realizar una busqueda exitosa, agregar o editar. Es decir con datos en vista.
        {
            estadoDelFormulario = "estEsperandoOperacion";

            System.Windows.Forms.Control[] controlesHabilitados = { this.txtCodBarra, this.btnBusCodigo, this.txtDescripcion, this.btnBusDescripcion };
            System.Windows.Forms.Control[] controlesDeshabilitados = { this.lstProductosCodBarra, this.lstProductosDescripcion };
            System.Windows.Forms.Control[] controlesVisibles = { };
            System.Windows.Forms.Control[] controlesInvisibles = { this.lstProductosCodBarra, this.lstProductosDescripcion,lblAviso ,lblError};

            habilitarControles(controlesHabilitados);
            deshabilitarControles(controlesDeshabilitados);
            visibleControles(controlesVisibles);
            invisibleControles(controlesInvisibles);

            if (refrescarResgProductos) //si hace falta actualizar el refrescarResgProducto se realiza
            {
                ejecutarHiloActualizarResgProductos();

            }

            cargarNombrePost();

            errorProvider1.Clear();  //se borran los errores, si habian.

            txtCodBarra.Focus();   //se deja el foco en txtCodBarra

            cboPostEnviar.SelectedIndex = -1;

            

            
        }

        private void limpiarDatos() //deja el formulario preparado para ingresar nuevos datos.
        {
            
            this.lblFechaValor.Text = "";
            this.lblTurnoValor.Text = "";
            this.lblNroValor.Text = "";
            this.lblUsuarioValor.Text = "";
            this.lblPostPedido.Text = "";
            this.lblDireccionValor.Text = "";
            this.lblEstadoValor.Text = "";
            this.cboPostEnviar.Text = "";

            this.txtCodBarra.Text = "";
            this.txtDescripcion.Text = "";

            this.dgvProductos.Rows.Clear();

        }

        
        //--------METODOS VARIOS---------------

        //Virtual, permite redefinir en frmAltaProductosDisueltos y frmRecibirProductos
        private void actualizarResgProductos() //Se refresca el arrayList resgProductos
        {
            try
            {
                //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ProductosTa.FillByProductos1(centerQuimDs,...);
                productosTa.FillByNoGranel(centerQuimDs.Productos);

                resgProductos.Clear(); //Se vacia resgProductos (ArrayList)

                foreach (DataRow unaFila in centerQuimDs.Productos) //Se recorre todas las filas  del centerQuimDs.Productos y se cargan los productos al ArrayList
                {
                    
                        resgProductos.Add(new Producto(Convert.ToString(unaFila[0]), Convert.ToString(unaFila[3])));
                    
                }

                refrescarResgProductos = false;

            }
            catch (IndexOutOfRangeException)
            {
                //si llega a ocurrir esta excepcion no se tiene en cuenta. Podría no haber productos cargados y lanzaría esta excepción.

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }

        }

        protected void btnBusCodigo_Click(object sender, EventArgs e)  //método que se ejecuta cuando se presiona sobre el botón btnBusCodigo
        {
            eventoBusCodigo();

        }

        protected virtual void eventoBusCodigo()  //Se encapsula en un método para que pueda usar cuando se presiona Enter sobre el txtCodBarra en estado de busqueda o click en btnBusCodBarra.
        {

            //no hace falta que pregunte si txtCodBarra es blanco, ya que por la forma de filtrar no encontrará nada igual.                                

            if (refrescarResgProductos)   //si es necesario actualizar el resgProductos se lo hace sino no
            {
                ejecutarHiloActualizarResgProductos();  //ejecuta el hilo que actualiza el ResgProductos
            }

            filtrarCodigoBarra();


            if (lstProductosCodBarra.Items.Count == 0)  //el filtro no obtuvo coincidencias.
            {
                //Se informa que no se encontró nada 
                MessageBox.Show("Su consulta no ha arrojado resultados.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                //Como no encontró nada se deja en este estado.
                this.estEsperandoOperacion();
            }
            else
            {
                if (lstProductosCodBarra.Items.Count == 1)   //solo se encontró una sola coincidencia. No es necesario mostrar el lstProductosCodBarra. Directamente se muestra el producto.
                {
                    this.estadoDelFormulario = "Buscando";  //Se coloca este estado ya que si encuentra algo, cargará el txtDescripcion y lanzará el evento TextChanged()

                    cargarProductoPorCodigo(this.txtCodBarra.Text.Trim());  //busca producto con codigo de barra único (una coincidencia) encontrado en el oHiloFiltrarCodBarra y lo carga en los textBox.

                    estEsperandoOperacion(); //se deja en el estado necesario

                }
                else
                {
                    //si se obtuvo más de una coincidencia, solo se muestran éstas en lstProductosCodBarra, y espera a que el usuario seleccione una.

                    lstProductosCodBarra.Visible = true;
                    lstProductosCodBarra.Enabled = true;

                    //lstProductosCodBarra.Focus(); //se deja el foco en el dgvProductosCodBarra para que elija alguna coincidencia.

                    //lstProductosCodBarra.SelectedIndex=0;  //se deja seleccionado el primer items.
                }

            }

        }

        protected void ejecutarHiloActualizarResgProductos() // hilo para actualizar el atributo ResgProductos
        {
            if ((oHiloActualizarResgProductos.ThreadState == ThreadState.Unstarted) || (oHiloActualizarResgProductos.ThreadState == ThreadState.Stopped))
            {
                this.oHiloActualizarResgProductos = new Thread(new ThreadStart(actualizarResgProductos));
                this.oHiloActualizarResgProductos.Priority = ThreadPriority.Highest;
                this.oHiloActualizarResgProductos.Start();  //Se ejecuta el hilo para actualizar el atributo ResgProductos
            }
        }



        protected virtual void cargarProductoPorCodigo(string unCodBarra) //busca producto con codigo de barra único (una coincidencia) encontrado en el oHiloFiltrarCodBarra y lo carga en los textBox.
        {
            try
            {
                //(ALE)HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ProductosTa.FillByProductos1(centerQuimDs,unCodBarra);
                productosTa.FillByCodigo(centerQuimDs.Productos, unCodBarra);

                //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
                dgvProductos.Rows.Add(centerQuimDs.Productos[0].codProducto, centerQuimDs.Productos[0].descripcion, "-", "-", "-", 0); //se carga un nuevo producto para enviar.


                //...
                //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected void filtrarCodigoBarra()  //Filtra y carga las descripciones (si las hay) en el lstProductos. Método que se ejecuta dentro de un hilo. 
        {

            this.oHiloActualizarResgProductos.Join(); //espera a que primero termine el oHiloActualizarResgProductos para proceder con el actual.

            lstProductosCodBarra.Items.Clear(); //vaciamos el lstProductosCodBarra por si tuviera descripciones anteriores.


            foreach (Producto unProducto in resgProductos) //buscamos las descripciones asociadas al código y la cargamos en el lstProductosCodBarra
            {
                if (this.txtCodBarra.Text.Trim() == unProducto.CodBarra)
                {
                    lstProductosCodBarra.Items.Add(unProducto.Descripcion);
                }

            }

        }

        protected void lstProductosCodBarra_DoubleClick(object sender, EventArgs e)  //captura en evento doble click sobre lstProductosCodBarra
        {
            procesarEleccionLstProductosCodBarra();
        }

        protected void procesarEleccionLstProductosCodBarra()  //se encapsulo para que se pueda usar con DoubleClick y Enter sobre el lstProductosCodBarra
        {
            try
            {
                this.estadoDelFormulario = "Buscando";  //Se coloca este estado ya que si encuentra algo, cargará el txtDescripcion y lanzará el evento TextChanged()

                cargarProductoPorDescripcion(lstProductosCodBarra.SelectedItem.ToString()); //busca producto por descripción en la base de datos, y lo carga en los textBox.

                estEsperandoOperacion(); //se deja en el estado necesario

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected virtual void cargarProductoPorDescripcion(string unaDescripcion)  //busca el producto por descripción en la base de datos y lo carga en los textbox.
        {
            //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
            productosTa.FillByNombre(centerQuimDs.Productos, unaDescripcion);

            //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
            //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
            dgvProductos.Rows.Add(centerQuimDs.Productos[0].codProducto, centerQuimDs.Productos[0].descripcion, "-", "-", "-", 0); //se carga un nuevo producto para enviar.

            //..
            //...
            //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.

        }

        protected void txtCodBarra_KeyDown(object sender, KeyEventArgs e)  //captura el evento KeyDown sobre el txtCodBarra.
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (estadoDelFormulario == "estEsperandoOperacion") //estado esperando operación o estado inicial
                {
                    eventoBusCodigo();

                }

            }
            else
            {
                if ((e.KeyCode == Keys.Down) & (lstProductosCodBarra.Items.Count > 0) & (estadoDelFormulario == "estEsperandoOperacion")) //Si se presiona para abajo y tiene a lstProductosDescripcion visible (es decir se encuentra esperando operacion y con items en la lista)
                {

                    lstProductosCodBarra.SetSelected(0, true); //se deja seleccionado el primer items
                    lstProductosCodBarra.Focus(); //Se deja el foco sobre este control para que seleccione un items.
                }
            }

        }

        protected void lstProductosCodBarra_Leave(object sender, EventArgs e) //Oculta automáticamente el lstProductosCodBarra cuando el control pierde el foco.
        {
            this.lstProductosCodBarra.Enabled = false;
            this.lstProductosCodBarra.Visible = false;
            this.lstProductosCodBarra.Items.Clear();
        }



        protected void txtDescripcion_TextChanged(object sender, EventArgs e) //evento que se desencadena cuando cambia el valor del TextBox
        {
            if (this.estadoDelFormulario == "estEsperandoOperacion") //el proceso es capturado solo si está en este estado.
            {
                eventoBusDescripcion();
            }

        }

        protected void eventoBusDescripcion()
        {
            if (txtDescripcion.Text != "") //Si txtDescripcion es distinto de blanco se realiza el procesamiento. Esto se realiza para no perder el tiempo en filtro innecesarios.
            {
                if (refrescarResgProductos)   //si es necesario actualizar el resgProductos se lo hace sino no
                {
                    ejecutarHiloActualizarResgProductos();
                }

                ejecutarHiloFiltrarDescripcion();

                if (lstProductosDescripcion.Items.Count == 0)  //el filtro no obtuvo coincidencias, no se muestra el lstProductosDescripcion
                {
                    lstProductosDescripcion.Visible = false;
                    lstProductosDescripcion.Enabled = false;

                }
                else
                {
                    lstProductosDescripcion.Visible = true; //si se obtuvo una o más coincidencia se muestran en lstProductosDescripcion, y espera a que el usuario seleccione una.
                    lstProductosDescripcion.Enabled = true;

                }

            }
            else  //Si txtDescripcion es blanco no se realiza el procesamiento
            {
                lstProductosDescripcion.Enabled = false;
                lstProductosDescripcion.Visible = false;
            }
        }

        protected void ejecutarHiloFiltrarDescripcion()
        {
            if ((this.oHiloFiltrarDescripcion.ThreadState == ThreadState.Unstarted) || (this.oHiloFiltrarDescripcion.ThreadState == ThreadState.Stopped))
            {
                this.oHiloFiltrarDescripcion = new Thread(new ThreadStart(filtrarDescripcion)); //Instancia el hilo y lo delega al metodo filtrarDescripcion. 
                this.oHiloFiltrarDescripcion.Priority = ThreadPriority.AboveNormal;
                this.oHiloFiltrarDescripcion.Start();  //hilo que filtra las descripciones asociadas al valor del txtDescripcion y lo carga en lstProductosDescripcion
            }

        }


        protected void filtrarDescripcion()
        {
            //this.oHiloActualizarResgProductos.Join(); //espera a que primero termine el oHiloActualizarResgProductos para proceder con el actual.

            lstProductosDescripcion.Items.Clear(); //vaciamos el lstProductosDescripcion por si tuviera descripciones anteriores.

            try
            {
                foreach (Producto unProducto in resgProductos) //buscamos las descripciones que coinciden con (al menos una palabra o letra + txtDescripcion.text + ninguna o muchas palabras o letras) y la cargamos en el lstProductosDescripcion
                {

                    if (Regex.Match(unProducto.Descripcion, txtDescripcion.Text.Trim().ToUpper()).Success)
                    {
                        lstProductosDescripcion.Items.Add(unProducto.Descripcion);
                    }

                }
            }
            catch (InvalidExpressionException)
            {

            }

            catch (Exception)
            {
                txtDescripcion.Text = "";

            }

        }

        protected void txtDescripcion_KeyDown(object sender, KeyEventArgs e) //Método que captura el evento de presión de una tecla sobre txtDescripcion
        {
            if ((e.KeyCode == Keys.Down) & (lstProductosDescripcion.Items.Count > 0) & (estadoDelFormulario == "estEsperandoOperacion")) //Si se presiona para abajo y tiene a lstProductosDescripcion visible (es decir se encuentra esperando operacion y con items en la lista)
            {

                lstProductosDescripcion.SetSelected(0, true); //se deja seleccionado el primer items
                lstProductosDescripcion.Focus(); //Se deja el foco sobre este control para que seleccione un items.

            }

        }



        protected void lstProductosDescripcion_Leave(object sender, EventArgs e) //Oculta automáticamente el lstProductosDescripcion cuando el control pierde el foco.
        {
            this.lstProductosDescripcion.Enabled = false;
            this.lstProductosDescripcion.Visible = false;
        }

        protected void lstProductosDescripcion_DoubleClick(object sender, EventArgs e) //evento que captura la elección de un item en el lstProductosDescripcion
        {
            procesarEleccionLstProductosDescripcion();
        }


        protected void procesarEleccionLstProductosDescripcion()  //Se encapsula para que capture Double click y Enter sobre  lstProductosDescripcion
        {
            try
            {
                this.estadoDelFormulario = "Buscando";

                cargarProductoPorDescripcion(lstProductosDescripcion.SelectedItem.ToString()); //busca producto por descripción y lo carga en los textBox.

                estEsperandoOperacion(); //se deja en el estado necesario

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected void btnBusDescripcion_Click(object sender, EventArgs e) //captura el evento Click sobre el boton btnBusDescripcion
        {
            eventoBusDescripcion();
        }

        protected void lstProductosCodBarra_KeyDown(object sender, KeyEventArgs e) //captura el evento keyDown cuando se presiona enter sobre lstProductosCodBarra
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesarEleccionLstProductosCodBarra();
            }
            else
            {
                if ((e.KeyCode == Keys.Up) & (lstProductosCodBarra.SelectedIndex == 0))//si llega al primer lugar y presiona para arriba, vuelve al txtCodBarra
                {
                    txtCodBarra.Focus();
                }
            }
        }

        protected void lstProductosDescripcion_KeyDown(object sender, KeyEventArgs e) //captura el evento keyDown cuando se presiona enter sobre lstProductosDescripcion
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesarEleccionLstProductosDescripcion();
            }
            else
            {
                if ((e.KeyCode == Keys.Up) & (lstProductosDescripcion.SelectedIndex == 0)) //si llega al primer lugar y presiona para arriba, vuelve al txtDescripcion
                {
                    txtDescripcion.Focus();
                }

            }
        }


        private void txtCodBarra_TextChanged(object sender, EventArgs e)  //si se modifica txtCodBarra, se oculta lstCodBarra
        {
            lstProductosCodBarra.Visible = false;
            lstProductosCodBarra.Enabled = false;
        }

        protected virtual void frmActualizarPreciosCentral_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F1)
            {

                bool tieneError = false;

                foreach (System.Windows.Forms.Control ctrl in this.Controls)
                {
                    if (errorProvider1.GetError(ctrl) != "")
                    {
                        tieneError = true;
                    }
                }

                if (tieneError) mostrarErrores();
            }
            else
            {
                if (e.KeyCode == Keys.F12)
                {
                    refrescarResgProductos = true;

                }
            }
        }

        private ArrayList obtenerNombresPost() //obtiene los nombres de los post.
        {
            string[] listaSubcarpetas; //variable que almacenará la lista de todas las subcarpetas dentro de Dropbox.
            listaSubcarpetas = Directory.GetDirectories("F:\\Dropbox"); //obtenemos la lista de las subcarpetas en Dropbox.

            ArrayList nombresPost = new ArrayList(); //creamos un arrayList, que almacenará solo los nombre de los post
            nombresPost.Clear(); //vaciamos el arrayList

            foreach (string unaSubcarpeta in listaSubcarpetas)
            {
                FileInfo unFileInfo = new FileInfo(unaSubcarpeta); //creamos un FileInfo que almacen
                if (Regex.Match(unFileInfo.Name, "POST*").Success)
                {
                    nombresPost.Add(unFileInfo.Name);
                }
            }

            return (nombresPost);

        }

        private void cargarNombrePost() //carga los nombres de los post en cboPost.
        {
            cboPost.Items.Clear(); //se vacia el cbo de post
            cboPostEnviar.Items.Clear(); // se vacia el cboEnviar

            
            ArrayList listaPost = new ArrayList(); //almacenara los nombres (string) de todos los post, para luego buscar sus nombres de pedidos.

            listaPost = obtenerNombresPost(); //se obtienen todos los nombre de post.

            foreach (string nombrePost in listaPost) //se cargan los nombres de los post en los combos correspondientes
            {
                cboPost.Items.Add(nombrePost);
                cboPostEnviar.Items.Add(nombrePost);
                
            }

            cboPost.SelectedIndex = 0; //colocamos el primer items en el comboBox.

        }

        private void cboPost_SelectedIndexChanged(object sender, EventArgs e) //se cargan las ordenes de compra del post seleccionado
        {
            this.cboPedido.Items.Clear(); //borra todo lo que tenía antes. 

            string directorioPedido = "F:\\Dropbox\\"+ cboPost.SelectedItem.ToString() +"\\Datos del Sistema\\Ordenes de Compra"; //seteamos el directorio desde donde leeremos los archivos

            foreach (string archivo in Directory.GetFiles(directorioPedido))  //por cada archvio en este directorio
            {
                FileInfo archivoInfo = new FileInfo(archivo);  //obtenemos información de ese directorio

                cboPedido.Items.Add(archivoInfo.Name); //mostramos solo su nombre corto.

            }

        }

        private void btnBusPedido_Click(object sender, EventArgs e) //metodo capturador de evento click sobre el boton lupa para buscar pedido.
        {
            leerArchivo(); //se procesa la lectura de la 

        }

        
        private void leerArchivo()
        {
            if (cboPedido.Text == "")
            {
                MessageBox.Show("Debe seleccionar un pedido para el post seleccionado.", "ENVIO DE PRODUCTOS", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }
            else
            {
                cboPostEnviar.Text = cboPost.Text; //se coloca el postEnvio desde donde se leerá la orden de pedido. 
                
                string nombreArchivo = "F:\\Dropbox\\"+cboPost.Text+"\\Datos del Sistema\\Ordenes de Compra\\"+cboPedido.Text;


                //guardar el archivo a través del objeto FileStream.
                try
                {
                    //abre el archivo para leerlo.
                    ordenCompraEntrada = new FileStream(nombreArchivo, FileMode.Open, FileAccess.Read); //crea el objeto FileStream para obtener acceso de lectura al archivo.

                    leerOrdenDeCompra();  //lee el encabezado y el cuerpo y lo muestra en el forms.

                    //cuando ya no tiene más datos se lanza la excepcion SerializationException para informar que terminó.

                }

                catch (SerializationException)
                {
                    MessageBox.Show("Orden de Compra leida con éxito!!", "ENVIAR PRODUCTOS", MessageBoxButtons.OK, MessageBoxIcon.Information);

                }

                catch (FormatException)
                {
                    //notifica al usuario si el archivo no existe
                    MessageBox.Show("Formato inválido", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                catch (IOException)
                {
                    //notifica al usuario si el archivo no existe
                    MessageBox.Show("Error al abrir el archivo", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                catch (Exception ex)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("La conexión a la base de datos no fué exitosa. /n /n Comuniquese con su desarrollador para solucionar el problema /n /n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    this.Close();
                }

                finally
                {
                    cerrarArchivo();
                }

            }

        }

        private void leerOrdenDeCompra()  //lee los datos de la orden de compra enviada por el cajero y lo carga a la grilla.
        {
            //-------LEER ENCABEZADOS-----------------
            RegistroOrdenCompra unRegistroOrdenCompra = (RegistroOrdenCompra)aplicadorFormato.Deserialize(ordenCompraEntrada);
            
            lblFechaValor.Text = unRegistroOrdenCompra.Fecha;
            lblTurnoValor.Text = unRegistroOrdenCompra.Turno;
            lblNroValor.Text = unRegistroOrdenCompra.CodOrdenPedido.ToString();
            lblUsuarioValor.Text = unRegistroOrdenCompra.CajeroNombre;
            lblEmitidoValor.Text = unRegistroOrdenCompra.PostNombre;
            lblDireccionValor.Text = unRegistroOrdenCompra.PostDirección;
            lblEstadoValor.Text = unRegistroOrdenCompra.Estado;

            dgvProductos.Rows.Clear(); //borramos las filas de la grilla.

            do
            {       //instanciamos un RegistroListaPrecio(Serializado) y le asignamos el primer objeto del archivo
                RegistroProductoOrdenCompra unRegistroProductoOrdenCompra = (RegistroProductoOrdenCompra)aplicadorFormato.Deserialize(ordenCompraEntrada);

                        //si el producto es terminado o disuelto vendido por cantidad (solo puede ser de este tipo el disuelto)
                if ((unRegistroProductoOrdenCompra.Descripcion.Substring(0,1) == "T") || (unRegistroProductoOrdenCompra.Descripcion.Substring(0,1) == "D"))
                {
                    dgvProductos.Rows.Add(unRegistroProductoOrdenCompra.CodProducto, unRegistroProductoOrdenCompra.Descripcion, Convert.ToInt32(unRegistroProductoOrdenCompra.StockActual), Convert.ToInt32(unRegistroProductoOrdenCompra.StockMinimo), Convert.ToInt32(unRegistroProductoOrdenCompra.Cantidad),0,false);
                }
                else 
                {
                    dgvProductos.Rows.Add(unRegistroProductoOrdenCompra.CodProducto, unRegistroProductoOrdenCompra.Descripcion, unRegistroProductoOrdenCompra.StockActual, unRegistroProductoOrdenCompra.StockMinimo, unRegistroProductoOrdenCompra.Cantidad,0,false);
                }


            } while (ordenCompraEntrada != null);

        }


        private void btnEnviarProductos_Click(object sender, EventArgs e)
        {
            if (formularioValido())
            {
                try
                {
                    DialogResult result = MessageBox.Show("¿Desea generar los siguientes productos para ser enviados a un post?", "CONFIRMACION ", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                    if (result == DialogResult.Yes)
                    {
                        this.Enabled = false;
                        lblAviso.Visible = true;

                        procesarEnvio();
                    }
                }


                catch (IndexOutOfRangeException)
                {

                }
                catch (Exception ex)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    //Si llega a ocurrir algún error en estado agregar 
                    this.Close();
                }

            }
            else
            {
                informarExistenciaError();
            }

        }

        private void procesarEnvio()
        {
            agregarRemito();  //agrega un registro de remito a la tabla de Remito

            agregarProductoXRemito(); //agrega un registro de productosXRemito a esa tabla

            crearArchivoRemito(); //se crea el archivo de pedido y se deja en el post seleccionado.

            decrementarStock(); //se decrementa el stock local.

            borrarArchivoPedido(); //se borra el archivo de pedido.

            imprimirEnvio();

            limpiarDatos();

            
            this.Enabled = true;
            this.lblAviso.Visible = false;

            this.estEsperandoOperacion(); //se vuelve al estado inicial.

            //Se muestra un mje de confirmación.
            MessageBox.Show("Envió generado con exito!!!", "AVISO", MessageBoxButtons.OK, MessageBoxIcon.Information);



        }

        private void borrarArchivoPedido() //se elimina el archivo de pedido leido, si es que leyo alguno.
        {
            if (lblEmitidoValor.Text != "")
            {
                if (ordenCompraEntrada != null)
                {
                    File.Delete(ordenCompraEntrada.Name);
                }

            }
                
   
        }

        private void agregarRemito()
        {

            remitosTa.Insert(Convert.ToDateTime(this.obtenerFechaActual()),obtenerCodUsuarioActual(),"",true,cboPostEnviar .SelectedItem .ToString ());


        }


        private void agregarProductoXRemito() //agrega un registro a la tabla ProductosXremito
        {
            int ultimoRemito = remitosTa.ScalarQueryUltimoRemito().Value; //obtiene el último remito

            foreach (DataGridViewRow row in dgvProductos.Rows)
            {
                
                if (Convert.ToBoolean(row.Cells[6].Value) == true) // si se encuentra seleccionado.
                {
                    productoxRemitoTa.Insert(ultimoRemito, row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString(), Convert.ToDouble(row.Cells[5].Value));

                }
                
            }

        }

        private void crearArchivoRemito()
        {

            int ultimoRemito = remitosTa.ScalarQueryUltimoRemito().Value;
            
            string nombreArchivo = "F:\\Dropbox\\" + cboPost.Text + "\\Datos del Sistema\\Remitos\\remito" + ultimoRemito.ToString() + ".cq"; //coloca el nombre del directorio y archivo completo.

            //guardar el archivo a través del objeto FileStream.
            try
            {
                remitoSalida = new FileStream(nombreArchivo, FileMode.OpenOrCreate, FileAccess.Write); //abre el archivo con acceso de escritura

                CargarDatosAlArchivo();

            }

            catch (SerializationException)
            {
                //notifica al usuario si el archivo no existe
                MessageBox.Show("Error al escribir en el archivo", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            catch (FormatException)
            {
                //notifica al usuario si el archivo no existe
                MessageBox.Show("Formato inválido", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            catch (IOException)
            {
                //notifica al usuario si el archivo no existe
                MessageBox.Show("Error al abrir el archivo", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                cerrarArchivo();
            }    
        }

        private void CargarDatosAlArchivo()
        {
            //---------ESCRIBIR ENCABEZADO---------------------
            
            int ultimoRemito = remitosTa.ScalarQueryUltimoRemito().Value;

            RegistroRemito unRegistroRemito;

            unRegistroRemito = new RegistroRemito(obtenerFechaActual(), "remcq" + ultimoRemito.ToString());  //El codRemito se pasa a "cq123"

            //escribe registro al objeto FileStream (serializa el objeto)
            aplicadorFormato.Serialize(remitoSalida, unRegistroRemito);

            //----------ESCRIBIR CUERPO-------------------------

            foreach (DataGridViewRow row in dgvProductos.Rows)
            {
                if (Convert.ToBoolean(row.Cells[6].Value) == true)
                {
                    RegistroProductoRemito unRegistroProductoRemito; //instanciamos un registroProductoRemito(Serializado) y le asignamos nombre.

                    unRegistroProductoRemito = new RegistroProductoRemito(Convert.ToString(row.Cells[0].Value), Convert.ToString(row.Cells[1].Value), Convert.ToDouble(row.Cells[5].Value));

                    //escribe registro al objeto FileStream (serializa el objeto)
                    aplicadorFormato.Serialize(remitoSalida, unRegistroProductoRemito);
                
                }
                
            }
        
        }



        private bool formularioValido() //método realiza todas las operaraciones de validación
        {
            validarNombrePost();

            validarGrilla();


            if ((errorProvider1.GetError(dgvProductos) == "") & (errorProvider1.GetError(cboPostEnviar) == ""))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void validarNombrePost() //valida que el tamaño de la caja de texto no pase de 50 caracteres.
        {
            if (cboPostEnviar.Text.Trim() == "")
            {
                errorProvider1.SetError(cboPostEnviar, "Nombre de Post: el campo se encuentra vacio\n\n");
            }
            else
            {
                errorProvider1.SetError(cboPostEnviar, new ValidarDatos().validarLongitud("Nombre de Post:", cboPostEnviar.Text, 50));

            }
        }

        private void validarGrilla() //recorre todo el dataGride y verifica que los datos se encuentren correctos, si alguno está incorrecto los pinta de blanco
        {
            bool grillaSinError = true;  //inicializa el booleano que controla si el dgvProductos tiene al menos un error.

            bool seleccionado = false; //inicializa el booleano que controla si el dgvProducto tiene al menos un elemento seleccionado

            foreach (DataGridViewRow row in dgvProductos.Rows)
            {

                if (Convert.ToBoolean(row.Cells[6].Value))  //si se encuentra seleccionada la fila
                {
                    seleccionado = true;

                    string tipo = Convert.ToString(row.Cells[1].Value).Substring(0, 1);  //obtiene si el tipo de producto en la fila, en base a la primera letra de la descripción

                    if (tipo == "T" || (tipo == "D"))
                    {
                        if ((new ValidarDatos().ValidarNaturalesPositivos("Fila:", Convert.ToString(row.Cells[5].Value))) == "") //No tiene error. El producto terminado o disuelto por cantidad.
                        {
                            row.Cells[5].Style.BackColor = Color.White;

                        }
                        else      //con error en producto terminado o disuelto por cantidad
                        {
                            row.Cells[5].Style.BackColor = Color.LightPink;

                            grillaSinError = false;
                        }

                    }
                    else
                    {
                        if ((new ValidarDatos().validarRealesPositvosSinCero("Fila:", Convert.ToString(row.Cells[5].Value))) == "") //No tiene error. El producto base.
                        {
                            row.Cells[5].Style.BackColor = Color.White;

                        }
                        else  //con error en producto base
                        {
                            row.Cells[5].Style.BackColor = Color.LightPink;

                            grillaSinError = false;
                        }
                    }

                }

            }

            if ((grillaSinError) & (seleccionado))
            {
                errorProvider1.SetError(dgvProductos, "");
            }
            else
            {
                if (grillaSinError == false)
                    errorProvider1.SetError(dgvProductos, "Algunos de los campos cantidad en la grilla no contiene datos válidos.");

                if (seleccionado == false)
                    errorProvider1.SetError(dgvProductos, "La grilla no contiene productos seleccionados.");
            }
        }

      
        private void cerrarArchivo()
        {
            try
            {
                if (ordenCompraEntrada != null)  //determina si existe el archivo
                {
                    ordenCompraEntrada.Close();  //cierra el archivo
                }

                if (remitoSalida != null)  //determina si existe el archivo
                {
                    remitoSalida.Close();  //cierra el archivo
                }
            }
            catch (IOException)  //notifica al usuario del error al cerrar el archivo
            {
                MessageBox.Show("No se puede cerrar el archivo.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
        }

        private void decrementarStock()
        {
            //base.redefenirStock();
            foreach (DataGridViewRow row in dgvProductos.Rows)//recorremos el datagride y actualizamos stock
            {
                if (Convert.ToBoolean(row.Cells[6].Value))  //si se encuentra seleccionada la fila
                {
                    productosTa.FillByNombre(centerQuimDs.Productos, row.Cells[1].Value.ToString());

                    double regStock = centerQuimDs.Productos[0].stockActual;

                    if (centerQuimDs.Productos[0].tipo == "B") //si el producto es base
                    {
                        productosTa.UpdateQueryStock(Convert.ToDecimal(centerQuimDs.Productos[0].stockActual) - Math.Round(Convert.ToDecimal(row.Cells[5].Value), 3), row.Cells[1].Value.ToString());
                        //centerQuimDs.Productos[0].stockActual -= Math.Round(Convert.ToDouble(row.Cells[5].Value), 3);
                    }
                    else //si no es base, entonces puede ser un terminado o un producto disuelto vendido por cantidad.
                    {
                        //centerQuimDs.Productos[0].stockActual -= Convert.ToInt32(row.Cells[5].Value);
                        productosTa.UpdateQueryStock(Convert.ToDecimal(centerQuimDs.Productos[0].stockActual) - Math.Round(Convert.ToDecimal(row.Cells[5].Value), 3), row.Cells[1].Value.ToString());
                    }

                    productosTa.FillByNombre(centerQuimDs.Productos, row.Cells[1].Value.ToString());

                    if (centerQuimDs.Productos[0].stockActual < 0) //si el stock que da negativo lo volvemos a cero e informamos el movimiento
                    {
                        productosTa.UpdateQueryStock(0, row.Cells[1].Value.ToString());
                        movimientosTa.InsertQueryMovimientosxProducto(row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString(), Convert.ToDateTime(obtenerFechaActual()), "A", "Stock Negativo Remito Nª" + remitosTa.ScalarQueryUltimoRemito().ToString(), Convert.ToDecimal(row.Cells[5].Value) - Convert.ToDecimal(regStock));
                    }
                    //productosTa.Update(centerQuimDs.Productos);

                    movimientosProductosBajaRemito(row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString(), Convert.ToDecimal(row.Cells[5].Value));
                
                }

            }

        }

        private void movimientosProductosBajaRemito(string codigo, string nombre, decimal cantidad)
        {
            int ultimoRemito = remitosTa.ScalarQueryUltimoRemito().Value; //obtiene el último remito

            movimientosTa.InsertQueryMovimientosxProducto(codigo, nombre, Convert.ToDateTime(obtenerFechaActual()), "B", "Envio Remito N°:" + ultimoRemito.ToString(), cantidad);
        }

        private void imprimirEnvio()
        {
            int ultimoRemito = Convert.ToInt32 (remitosTa.ScalarQueryUltimoRemito()); //buscamos el ultimo remito
            productoxRemitoTa.FillByNroRemito(centerQuimDs.productoxRemito, ultimoRemito);



            //Creamos una instancia de un objeto DataTable, y le hacemos que referencie a la tabla en CenterQuimDsCentral.productoXRemito
            DataTable unaDataTable = new DataTable();
            unaDataTable = centerQuimDs.productoxRemito;

            //creamos una instancia del tipo CrystalReports que habiamos creado y le asignamos a su crvEnvio la tabla instanciada y parametros necesarios.
            crEnvío unCrEnvio = new crEnvío();
            unCrEnvio.SetDataSource(unaDataTable);

            unCrEnvio.SetParameterValue("fechaValor", obtenerFechaActual());
            unCrEnvio.SetParameterValue("destinoValor", cboPostEnviar.Text );

            //creamos una instancia del frmReporteEnvio y le asignamos a su CrystalReportViewer el CrystalReports seteado
            FrmReporteEnvio unFrmReportePedido = new FrmReporteEnvio();
            unFrmReportePedido.crvEnvio.ReportSource = unCrEnvio;

            //mostramos el frmReporteVenta
            unFrmReportePedido.ShowDialog();
        }


        private int obtenerCodUsuarioActual()  //Dato necesario para la apertura de una caja
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getCodUsuario();
        }

        private string obtenerFechaActual()  //Dato necesario para el alta de venta
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getFechaActual();
        }


    }
}
